

import java.util.ArrayList;
import java.util.List;

import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.AfterClass;

public class RockPaperScissorsTest {
	
	private RockPaperScissors rps;
	private Player playerROCK,playerSCISSORS, playerPAPER, randomplayer1, randomplayer2, player1, player2, copyROCK, copySCISSORS, copyPAPER, copy1, copy2;
	
  @BeforeClass
  public void setUpClass(){
	  rps = new RockPaperScissors();
	  
	  List l1 = new ArrayList<RPSEnum>();
	  for(int i=0;i<10;i++)
		  l1.add(RPSEnum.ROCK);
	  playerROCK = new Player("PlayerROCK", l1);//all rock moves
	  copyROCK = new Player("copyROCK",l1);//all rock moves
	  
	  l1 = new ArrayList<RPSEnum>();
	  for(int i=0;i<10;i++)
		  l1.add(RPSEnum.SCISSORS);
	  playerSCISSORS = new Player("PlayerSCISSORS", l1);//all scissors moves
	  copySCISSORS = new Player("copySCISSORS",l1);//all scissors moves
	  
	  l1 = new ArrayList<RPSEnum>();
	  for(int i=0;i<10;i++)
		  l1.add(RPSEnum.PAPER);
	  playerPAPER = new Player("PlayerPAPER", l1); //all paper moves
	  copyPAPER = new Player("copyPAPER",l1);//all paper moves
	  
	  l1 = new ArrayList<RPSEnum>();
	  for(int i=0;i<8;i++)
		  l1.add(RPSEnum.ROCK);
	  for(int i=0;i<2;i++)
		  l1.add(RPSEnum.PAPER);
	  player1 = new Player("player1", l1); //mixed moves
	  copy1 = new Player("copy1", l1); //same mixed moves
	  
	  l1 = new ArrayList<RPSEnum>();
	  for(int i=0;i<8;i++)
		  l1.add(RPSEnum.SCISSORS);
	  for(int i=0;i<2;i++)
		  l1.add(RPSEnum.ROCK);
	  player2 = new Player("player2", l1); //mixed moves
	  copy2 = new Player("copy2", l1); //same mixed moves
	  
	  randomplayer1 = new Player("r1");  //random moves
	  randomplayer2 = new Player("r2");  //random moves
	  
  }

  @AfterClass
  public void tearDownClass() {
	  rps = null;
	  player1=null;
	  player2=null;
	  playerROCK=null;
	  playerSCISSORS=null;
	  playerPAPER=null;
	  randomplayer1=null;
	  randomplayer2=null;
	  copy1 = null;
	  copy2 = null;
	  copyROCK = null;
	  copyPAPER = null;
	  copySCISSORS = null;
  }
  
  @DataProvider(name = "Win")
  public Object[][] createWinData() {
   return new Object[][] {
     { RPSEnum.PAPER, RPSEnum.ROCK },
     { RPSEnum.SCISSORS, RPSEnum.PAPER },
     { RPSEnum.ROCK, RPSEnum.SCISSORS },
   };
  }
  
  @DataProvider(name = "Tie")
  public Object[][] createTieData() {
   return new Object[][] {
     { RPSEnum.PAPER, RPSEnum.PAPER },
     { RPSEnum.SCISSORS, RPSEnum.SCISSORS },
     { RPSEnum.ROCK, RPSEnum.ROCK },
   };
  }
  
  @DataProvider(name = "Lost")
  public Object[][] createLostData() {
   return new Object[][] {
     { RPSEnum.PAPER, RPSEnum.SCISSORS },
     { RPSEnum.ROCK, RPSEnum.PAPER },
     { RPSEnum.SCISSORS, RPSEnum.ROCK },
   };
  }
  
  @DataProvider(name = "WinSession")
  public Object[][] createWinSession() {
   return new Object[][] {
     { playerROCK, playerSCISSORS },
     { playerSCISSORS, playerPAPER },
     { playerPAPER, playerROCK },
     { player1, playerROCK },
     { player1, playerSCISSORS },
     { playerPAPER, player1 },
     { playerROCK, player2 },
     { player2, playerSCISSORS },
     { player2, playerPAPER },
     { player1, player2 },
   };
  }
  
  @DataProvider(name = "LostSession")
  public Object[][] createLostsession() {
   return new Object[][] {
		   { playerSCISSORS, playerROCK },
		     { playerPAPER, playerSCISSORS },
		     { playerROCK, playerPAPER },
		     { playerROCK, player1 },
		     { playerSCISSORS, player1 },
		     { player1, playerPAPER },
		     { player2, playerROCK },
		     { playerSCISSORS, player2 },
		     { playerPAPER, player2 },
		     { player2, player1 },
   };
  }
  
  @DataProvider(name = "TieSession")
  public Object[][] createTiesession() {
   return new Object[][] {
		   { playerSCISSORS, copySCISSORS },
		     { playerPAPER, copyPAPER },
		     { playerROCK, copyROCK },
		     { player1, copy1 },
		     { player2, copy2 },
   };
  }


  @Test (dataProvider = "Win")
  public void testWinPlay(RPSEnum p1, RPSEnum p2) {
    //throw new RuntimeException("Test not implemented");
	 assert Result.WIN.equals(rps.play(p1, p2)); 
  }
  
  @Test (dataProvider = "Tie")
  public void testTiePlay(RPSEnum p1, RPSEnum p2){
	  assert Result.TIE.equals(rps.play(p1, p2)); 
  }
  
  @Test (dataProvider = "Lost")
  public void testLostPlay(RPSEnum p1, RPSEnum p2){
	  assert Result.LOST.equals(rps.play(p1, p2)); 
  }
  
  @Test (dataProvider = "WinSession")
  public void testPlayersWin(Player p1, Player p2){
	  assert Result.WIN.equals(rps.play(p1, p2)); 
  }
  
  @Test (dataProvider = "LostSession")
  public void testPlayersLost(Player p1, Player p2){
	  assert Result.LOST.equals(rps.play(p1, p2)); 
  }
  
  @Test (dataProvider = "TieSession")
  public void testPlayersTie(Player p1, Player p2){
	  assert Result.TIE.equals(rps.play(p1, p2)); 
  }
  
  @Test
  public void testPlayersRandom(){
	  
	  Result result = rps.play(randomplayer1, randomplayer2);
	  
	  if(Result.TIE.equals(result)){
		  Assert.assertTrue( randomplayer1.getScore() == randomplayer2.getScore());
	  }
	  else if(Result.WIN.equals(result)){
		  Assert.assertTrue( randomplayer1.getScore() > randomplayer2.getScore());
	  }
	  else if(Result.LOST.equals(result)){
		  Assert.assertTrue( randomplayer1.getScore() < randomplayer2.getScore());
	  }
		  
  }
  
}
